package com.zidongxiangxi.rabbit.consumer.support;

import com.zidongxiangxi.rabbit.consumer.interceptor.IdempotentOperationsInterceptor;
import com.zidongxiangxi.rabbit.consumer.interceptor.SequenceOperationsInterceptor;
import org.aopalliance.aop.Advice;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
 * rabbit监听容器的后置处理类
 * 用于自己定义的RabbitListenerContainer
 *
 * @author chenxudong
 * @date 2020/11/07
 */
public class RabbitListenerContainerBeanPostProcessor implements BeanPostProcessor, Ordered {
	private final SequenceOperationsInterceptor sequenceInterceptor;
	private final IdempotentOperationsInterceptor idempotentInterceptor;

	public RabbitListenerContainerBeanPostProcessor(
			ObjectProvider<SequenceOperationsInterceptor> sequenceInterceptorProvider,
			ObjectProvider<IdempotentOperationsInterceptor> idempotentInterceptorProvider
	) {
		SequenceOperationsInterceptor sequenceOperationsInterceptorInSpring = null;
		try {
			sequenceOperationsInterceptorInSpring = sequenceInterceptorProvider.getIfUnique();
		} catch (Throwable ignore) {}
		sequenceInterceptor = sequenceOperationsInterceptorInSpring;
		IdempotentOperationsInterceptor idempotentOperationsInterceptorInSpring = null;
		try {
			idempotentOperationsInterceptorInSpring = idempotentInterceptorProvider.getIfUnique();
		} catch (Throwable ignore) {}
		idempotentInterceptor = idempotentOperationsInterceptorInSpring;
	}

	@Override
	public int getOrder() {
		return LOWEST_PRECEDENCE - 1;
	}

	@Override
	public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
		if (Objects.isNull(idempotentInterceptor)
				&& Objects.isNull(sequenceInterceptor)) {
			return bean;
		}
		if (!(bean instanceof SimpleMessageListenerContainer)) {
			return bean;
		}
		Field adviceChainField = ReflectionUtils.findField(SimpleMessageListenerContainer.class, "adviceChain");
		if (Objects.isNull(adviceChainField)) {
			return bean;
		}
		adviceChainField.setAccessible(true);
		Advice[] advices = (Advice[])ReflectionUtils.getField(adviceChainField, bean);
		boolean needSetIdempotent = Objects.nonNull(idempotentInterceptor);
		boolean needSetSequence = Objects.nonNull(sequenceInterceptor);
		if (Objects.nonNull(advices)) {
			for (Advice advice : advices) {
				if (needSetIdempotent && advice instanceof IdempotentOperationsInterceptor) {
					needSetIdempotent = false;
				} else if (needSetSequence && advice instanceof SequenceOperationsInterceptor) {
					needSetSequence = false;
				}
			}
		}
		List<Advice> adviceList = new LinkedList<>();
		if (needSetSequence) {
			adviceList.add(sequenceInterceptor);
		}
		if (Objects.nonNull(advices) && advices.length > 0) {
			Collections.addAll(adviceList, advices);
		}
		if (needSetIdempotent) {
			adviceList.add(idempotentInterceptor);
		}
		SimpleMessageListenerContainer messageListenerContainer = (SimpleMessageListenerContainer)bean;
		// 强制消费失败是返回队列，除非走到了MessageRecover
		messageListenerContainer.setDefaultRequeueRejected(true);
		messageListenerContainer.setAdviceChain(adviceList.toArray(new Advice[0]));
		return bean;
	}
}
